/**
 * 甘特图错误处理器
 * 提供统一的错误处理、日志记录和恢复机制
 */

export const ErrorType = {
  RENDER_ERROR: 'RENDER_ERROR',
  DATA_ERROR: 'DATA_ERROR',
  CANVAS_ERROR: 'CANVAS_ERROR',
  INTERACTION_ERROR: 'INTERACTION_ERROR',
  PERFORMANCE_ERROR: 'PERFORMANCE_ERROR',
  MEMORY_ERROR: 'MEMORY_ERROR',
} as const;

export type ErrorType = (typeof ErrorType)[keyof typeof ErrorType];

export interface GanttError {
  type: ErrorType;
  message: string;
  originalError?: Error;
  context?: Record<string, any>;
  timestamp: number;
  severity: 'low' | 'medium' | 'high' | 'critical';
}

export interface ErrorRecoveryStrategy {
  canRecover: boolean;
  recoveryAction?: () => void;
  fallbackData?: any;
  retryCount?: number;
  maxRetries?: number;
}

class GanttErrorHandler {
  private errors: GanttError[] = [];
  private maxErrorHistory = 100;
  private errorListeners: ((error: GanttError) => void)[] = [];

  // 记录错误
  logError(
    type: ErrorType,
    message: string,
    originalError?: Error,
    context?: Record<string, any>,
    severity: GanttError['severity'] = 'medium'
  ): GanttError {
    const error: GanttError = {
      type,
      message,
      originalError,
      context,
      timestamp: Date.now(),
      severity,
    };

    // 添加到错误历史
    this.errors.unshift(error);
    if (this.errors.length > this.maxErrorHistory) {
      this.errors.pop();
    }

    // 控制台输出
    const logMethod = this.getLogMethod(severity);
    logMethod(`[甘特图错误] ${type}: ${message}`, {
      originalError,
      context,
    });

    // 通知监听器
    this.notifyListeners(error);

    return error;
  }

  // 尝试错误恢复
  attemptRecovery(error: GanttError): ErrorRecoveryStrategy {
    switch (error.type) {
      case ErrorType.CANVAS_ERROR:
        return this.handleCanvasError(error);
      case ErrorType.DATA_ERROR:
        return this.handleDataError(error);
      case ErrorType.RENDER_ERROR:
        return this.handleRenderError(error);
      case ErrorType.INTERACTION_ERROR:
        return this.handleInteractionError(error);
      case ErrorType.PERFORMANCE_ERROR:
        return this.handlePerformanceError(error);
      case ErrorType.MEMORY_ERROR:
        return this.handleMemoryError(error);
      default:
        return { canRecover: false };
    }
  }

  // Canvas 错误处理
  private handleCanvasError(_error: GanttError): ErrorRecoveryStrategy {
    return {
      canRecover: true,
      recoveryAction: () => {
        console.log('尝试重新初始化Canvas...');
        // 清除现有 canvas
        // 重新创建 canvas
        // 重新绑定事件
      },
      retryCount: 0,
      maxRetries: 3,
    };
  }

  // 数据错误处理
  private handleDataError(_error: GanttError): ErrorRecoveryStrategy {
    return {
      canRecover: true,
      recoveryAction: () => {
        console.log('使用备用数据...');
      },
      fallbackData: {
        rooms: [],
        availabilities: [],
      },
      retryCount: 0,
      maxRetries: 2,
    };
  }

  // 渲染错误处理
  private handleRenderError(_error: GanttError): ErrorRecoveryStrategy {
    return {
      canRecover: true,
      recoveryAction: () => {
        console.log('降级渲染模式...');
        // 使用简化的渲染模式
        // 减少渲染复杂度
      },
      retryCount: 0,
      maxRetries: 2,
    };
  }

  // 交互错误处理
  private handleInteractionError(_error: GanttError): ErrorRecoveryStrategy {
    return {
      canRecover: true,
      recoveryAction: () => {
        console.log('重置交互状态...');
        // 清除所有交互状态
        // 重新绑定事件监听器
      },
      retryCount: 0,
      maxRetries: 3,
    };
  }

  // 性能错误处理
  private handlePerformanceError(_error: GanttError): ErrorRecoveryStrategy {
    return {
      canRecover: true,
      recoveryAction: () => {
        console.log('启用性能优化模式...');
        // 减少渲染频率
        // 启用虚拟化
        // 简化动画效果
      },
      retryCount: 0,
      maxRetries: 1,
    };
  }

  // 内存错误处理
  private handleMemoryError(_error: GanttError): ErrorRecoveryStrategy {
    return {
      canRecover: true,
      recoveryAction: () => {
        console.log('执行内存清理...');
        // 清理缓存
        // 释放不必要的引用
        // 触发垃圾回收
        if (window.gc) {
          window.gc();
        }
      },
      retryCount: 0,
      maxRetries: 1,
    };
  }

  // 获取日志方法
  private getLogMethod(severity: GanttError['severity']) {
    switch (severity) {
      case 'low':
        return console.log;
      case 'medium':
        return console.warn;
      case 'high':
      case 'critical':
        return console.error;
      default:
        return console.log;
    }
  }

  // 通知错误监听器
  private notifyListeners(error: GanttError) {
    this.errorListeners.forEach(listener => {
      try {
        listener(error);
      } catch (e) {
        console.error('错误监听器执行失败:', e);
      }
    });
  }

  // 添加错误监听器
  addErrorListener(listener: (error: GanttError) => void) {
    this.errorListeners.push(listener);
  }

  // 移除错误监听器
  removeErrorListener(listener: (error: GanttError) => void) {
    const index = this.errorListeners.indexOf(listener);
    if (index > -1) {
      this.errorListeners.splice(index, 1);
    }
  }

  // 获取错误历史
  getErrorHistory(): GanttError[] {
    return [...this.errors];
  }

  // 获取错误统计
  getErrorStats() {
    const stats = {
      total: this.errors.length,
      byType: {} as Record<ErrorType, number>,
      bySeverity: {} as Record<GanttError['severity'], number>,
      recentErrors: this.errors.slice(0, 10),
    };

    this.errors.forEach(error => {
      stats.byType[error.type] = (stats.byType[error.type] || 0) + 1;
      stats.bySeverity[error.severity] =
        (stats.bySeverity[error.severity] || 0) + 1;
    });

    return stats;
  }

  // 清理错误历史
  clearErrorHistory() {
    this.errors = [];
  }
}

// 创建全局错误处理器实例
export const ganttErrorHandler = new GanttErrorHandler();

// 错误处理装饰器
export function withErrorHandling<T extends (...args: any[]) => any>(
  fn: T,
  errorType: ErrorType,
  context?: Record<string, any>
): T {
  return ((...args: any[]) => {
    try {
      return fn(...args);
    } catch (error) {
      ganttErrorHandler.logError(
        errorType,
        `函数 ${fn.name} 执行失败: ${(error as Error).message}`,
        error as Error,
        context,
        'medium'
      );

      // 尝试恢复
      const recovery = ganttErrorHandler.attemptRecovery({
        type: errorType,
        message: (error as Error).message,
        originalError: error as Error,
        context,
        timestamp: Date.now(),
        severity: 'medium',
      });

      if (recovery.canRecover && recovery.recoveryAction) {
        recovery.recoveryAction();
      }

      throw error;
    }
  }) as T;
}

// 安全执行函数
export async function safeExecute<T>(
  fn: () => T | Promise<T>,
  errorType: ErrorType,
  fallbackValue?: T,
  context?: Record<string, any>
): Promise<T | undefined> {
  try {
    return await fn();
  } catch (error) {
    ganttErrorHandler.logError(
      errorType,
      `安全执行失败: ${(error as Error).message}`,
      error as Error,
      context,
      'medium'
    );

    if (fallbackValue !== undefined) {
      return fallbackValue;
    }

    return undefined;
  }
}
